package com.smashcrush.server.service.impl;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.htmlunit.HtmlUnitDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.smashcrush.model.BrowserType;
import com.smashcrush.model.Script;
import com.smashcrush.server.service.BrowserService;
import com.smashcrush.server.service.ScriptService;

@Service
public class BrowserServiceImpl implements BrowserService {

	@Autowired
	ScriptService scriptService;

	Map<String, WebDriver> browsers = new HashMap<String, WebDriver>();

	@Override
	public String openSession(String token, BrowserType browserType) {

		String guid = UUID.randomUUID().toString();
		DesiredCapabilities c = new DesiredCapabilities();

		WebDriver driver = null;

		if (browserType.equals(BrowserType.Chrome)) {
			driver = new ChromeDriver();
		} else if (browserType.equals(BrowserType.FireFox)) {
			driver = new FirefoxDriver();
		} else if (browserType.equals(BrowserType.HtmlUnit)) {
			driver = new HtmlUnitDriver();
		} else if (browserType.equals(BrowserType.IE)) {
			driver = new InternetExplorerDriver();
		}

		browsers.put(guid, driver);

		return guid;
	}

	@Override
	public Map<String, String> executeScriptByName(String token, String name,
			Map<String, String> parameters) {

		Script script = scriptService.getScript(token, name);

		String sessionId = openSession(token, script.getBrowserType());

		Map<String, String> results = executeScript(token, sessionId, script
				.getSource(), parameters);

		closeSession(token, sessionId);

		return results;
	}

	public Map<String, String> executeScriptByName(String token,
			String sessionId, String name, Map<String, String> parameters) {

		Script script = scriptService.getScript(token, name);

		return executeScript(token, sessionId, script.getSource(), parameters);
	}

	@Override
	public Map<String, String> executeScript(String token,
			BrowserType browserType, String script,
			Map<String, String> parameters) {

		String sessionId = openSession(token, browserType);

		Map<String, String> results = executeScript(token, sessionId, script,
				parameters);

		closeSession(token, sessionId);

		return results;
	}

	public Map<String, String> executeScript(String token, String sessionId,
			String script, Map<String, String> parameters) {

		Map<String, String> results = new HashMap<String, String>();

		ScriptEngineManager factory = new ScriptEngineManager();
		ScriptEngine engine = factory.getEngineByName("groovy");

		WebDriver browser = browsers.get(sessionId);

		engine.put("browser", browser);
		engine.put("results", results);

		try {
			engine.eval("import org.openqa.selenium.By\n" + script);
		} catch (ScriptException e) {
			e.printStackTrace();
			throw new RuntimeException(e);
		}

		return results;
	}

	public void closeSession(String token, String sessionId) {
		WebDriver webdriver = browsers.get(sessionId);
		webdriver.close();
		browsers.remove(sessionId);
	}

}
